#!/usr/bin/env python2
#
# Clipbox v0.3a
# Created by Andrew Dunai <anderson.dunai@gmail.com>
# http://andrewdunai.com
#
# This file is part of Clipbox.
#
# Clipbox is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Clipbox is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Clipbox.  If not, see <http://www.gnu.org/licenses/>.

import sys
sys.path.append('./')
import pyperclip
import log
from threading import Thread
import time
import urllib, urllib2
import json

HOST = 'http://clipbox.andrewdunai.com'


class Clipboard(Thread):
    '''
    Cooperative clipboard service daemon.
    '''
    def __init__(self):
        '''
        Constructor.
        '''
        Thread.__init__(self)
        self._last_data = self._get_data()
        self._last_id = 0
        self._paused = False
        self.password = 'test'

    def set_password(self, password):
        '''
        Password setter
        '''
        self.password = password

    def _get_data(self):
        '''
        Return current local clipboard content.
        Calling this function periodically is the only way to detect local clipboard changes.
        '''
        return pyperclip.paste()

    def _data_changed_event(self, data):
        '''
        Data change event.
        Triggered when user hits CTRL+C or local clipboard content is changed in any other way.
        Updates remote clipboard with local data.
        '''
        log.d('New data in clipboard: %s' % data.replace('\n', '\\n'))
        if data.startswith('file:///'):
            # This is file.
            # Unfortunately, this is not yet implemented.
            log.e('Files copy-pasting not yet implemented')
            return
        # Update remote clipboard
        req = urllib2.Request('%s/set/%s/' % (HOST, self.password), urllib.urlencode({'data':data}), {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'})
        response = urllib2.urlopen(req)
        response = json.loads(response.read())
        # Update data version
        self._last_id = response['last_id']

    def run(self):
        '''
        Thread body.
        Tries to update local clipboard with remove data and monitors local clipboard changes.
        '''
        while True:
            time.sleep(0.5)
            # Request info about remote clipboard
            response = urllib2.urlopen('%s/get/%s/?last_id=%s' % (HOST, self.password, self._last_id))
            response = json.loads(response.read())
            if not (response['data'] is None) and self._last_data != response['data']:
                # If response['data'] is not None, then someone updated remote clipboard.
                log.d('Got new data: %s' % response['data'])
                # Update local clipboard data
                pyperclip.copy(response['data'])
                # Update _last_data to prevent _data_changed_event from firing (because we don't need to update remove clipboard)
                self._last_data = response['data']
                # Update data version
                self._last_id = response['last_id']
                continue

            # Check local clipboard changes and trigger _data_changed_event if it changed.
            data = self._get_data()
            if data != self._last_data:
                self._last_data = data
                self._data_changed_event(data)


if __name__ == '__main__':
    '''
    Application entry point.
    '''
    # Usage instructions
    if len(sys.argv) != 2:
        log.e('Usage: clipbox <password>')
        sys.exit(1)
    # Init clipboard
    clipboard = Clipboard()
    # Set password
    clipboard.set_password(sys.argv[1])
    # Run clipboard daemon
    clipboard.start()
    log.i('Clipboard started')
